#include "ebookpath.h"
#include "ui_ebookpath.h"
#include "sql.h"
#include <QFileDialog>
#include <QDebug>
#include <QShortcut>
#include <QRegExpValidator>
#include <QListView>
#include <QTreeView>
#include <QMessageBox>

EbookPath::EbookPath(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::EbookPath)
{
    ui->setupUi(this);

    //使每次弹窗都在最前面
    setWindowFlag(Qt::WindowStaysOnTopHint);

    QShortcut *keyR=new QShortcut(QKeySequence(Qt::Key_Return),this); //大键盘的回车键
    connect(keyR,SIGNAL(activated()),this,SLOT(on_ptnConfirmOtherType_clicked()));
    QShortcut *keyE=new QShortcut(QKeySequence(Qt::Key_Enter),this);  //数字键盘的回车键
    connect(keyE,SIGNAL(activated()),this,SLOT(on_ptnConfirmOtherType_clicked()));

    //添加其他文件格式，对输入进行限制，只允许大小写字母、数字和英文分号
    QRegExpValidator *pReg = new QRegExpValidator(QRegExp("[a-zA-Z0-9;]{60}"), this);
    ui->leOtherType->setValidator(pReg);

    //默认选中"不限类型"
    ui->tBSelectedType->setText("不限类型");
    flagSetup_rBTypeIgnore = true;
    ui->rBTypeIgnore->setChecked(true);
    flagSetup_rBTypeIgnore = false; //将"不限类型"设定成非选中后，要将标志重置为false

    firstShow();
}

EbookPath::~EbookPath()
{
    delete ui;
}

void EbookPath::firstShow()
{
    //如果数据库中保存了电子书路径，在弹窗时载入并显示到界面上
    ui->listWidgetDir->clear();
    m_dirVec.clear();
    m_dirVec = Sql::getInstance()->getBookDir();
    qDebug() << "dirInDb="<<m_dirVec;
    if (m_dirVec.size() > 0)
    {
        for (QString dir : m_dirVec)
        {
            QListWidgetItem *item = new QListWidgetItem;
            item->setText(dir);
            ui->listWidgetDir->addItem(item);
            ui->listWidgetDir->setCurrentItem(item); //默认选中刚添加的行
        }
        ui->ptnDeleteDir->setEnabled(true);
        ui->ptnClearDir->setEnabled(true);
    }
    else
    {
        ui->ptnDeleteDir->setEnabled(false); //设置删除按钮为不可用
        ui->ptnClearDir->setEnabled(false);  //设置清空按钮为不可用
    }
}

//判断是否为全部非选中
bool EbookPath::isAllUnchecked()
{
    if (ui->leOtherType->text().length() == 0 &&
        ui->cB_pdf->checkState() == Qt::CheckState::Unchecked &&
        ui->cB_mobi->checkState() == Qt::CheckState::Unchecked &&
        ui->cB_epub->checkState() == Qt::CheckState::Unchecked &&
        ui->cB_azw3->checkState() == Qt::CheckState::Unchecked &&
        ui->cB_txt->checkState() == Qt::CheckState::Unchecked &&
        ui->cB_caj->checkState() == Qt::CheckState::Unchecked &&
        ui->cB_docOrdocx->checkState() == Qt::CheckState::Unchecked)
    {
        return true;
    }
    return false;
}

//单独点击选中或非选中"限定类型"的操作
void EbookPath::subTypeSelect(int arg1, QString fileType)
{
    if (2 == arg1)
    {
        ui->rBTypeIgnore->setChecked(false);
        m_eBookType.append(fileType);
    }
    else if (0 == arg1)
    {
        //取消选中，移除m_eBookType中对应的文件类型
        m_eBookType.removeAt(m_eBookType.indexOf(fileType));

        //判断其他选项是否都没有选中，且其他格式的输入也为空，如果都满足，要将"不限类型"按钮设置为选中
        if (isAllUnchecked())
        {
            flagSetup_rBTypeIgnore = true;
            ui->rBTypeIgnore->setChecked(true);
            flagSetup_rBTypeIgnore = false; //将"不限类型"设定成非选中后，要将标志重置为false
        }
    }

    displaySelectType(); //将选中的文件类型在界面显示出来

#if 0
    qDebug() << "<cB_" << fileType <<",m_eBookTypeSize="<<m_eBookType.size();
    for (QString s:m_eBookType)
    {
        qDebug() << "----m_eBookType="<<s;
    }
#endif  
}

//将选中的文件类型在界面显示出来
void EbookPath::displaySelectType()
{
    QString strType;
    for (int i = 0; i < m_eBookType.size(); ++i)
    {
        strType.append(m_eBookType[i]);
        if ( i != m_eBookType.size()-1)
        {
            strType.append(";");
        }
    }
    ui->tBSelectedType->setText(strType);
}

//提供主界面清空所有数据使用
void EbookPath::clearAll()
{
    ui->listWidgetDir->clear();          //清空listWidget
    m_dirVec.clear();                    //清空m_dirVec变量
    Sql::getInstance()->clearBookDir();  //清空数据库
    ui->ptnDeleteDir->setEnabled(false); //设置删除按钮为不可用
    ui->ptnClearDir->setEnabled(false);  //设置清空按钮为不可用
    ui->ptnAddDir->setFocus();
}

//"不限类型"按钮槽函数
void EbookPath::on_rBTypeIgnore_clicked()
{
    bool isUnchecked = false;
    //flagSetup_rBTypeIgnore为true，表示在代码中对"不限类型"按钮进行操作，需要进行限制
    if (!flagSetup_rBTypeIgnore)
    {
        ui->cB_pdf->setCheckState(Qt::CheckState::Unchecked);
        ui->cB_mobi->setCheckState(Qt::CheckState::Unchecked);
        ui->cB_epub->setCheckState(Qt::CheckState::Unchecked);
        ui->cB_azw3->setCheckState(Qt::CheckState::Unchecked);
        ui->cB_txt->setCheckState(Qt::CheckState::Unchecked);
        ui->cB_caj->setCheckState(Qt::CheckState::Unchecked);
        ui->cB_docOrdocx->setCheckState(Qt::CheckState::Unchecked);
        ui->leOtherType->setText("");
        ui->tBSelectedType->setText("");

        //如果取消选中，默认选中"限定类型"中的"pdf"类型
        if (!ui->rBTypeIgnore->isChecked())
        {
            isUnchecked = true;
            ui->cB_pdf->setCheckState(Qt::CheckState::Checked);
        }
    }
    //如果取消选中，会默认选中"pdf"，不能清空m_eBookType
    if (!isUnchecked)
    {
        ui->tBSelectedType->setText("不限类型");
        m_eBookType.clear();  //清空，限定类型会在调用setCheckState时移除，手动添加的其他类型要在这里清空
    }
}

//添加其他文件格式槽函数
void EbookPath::on_ptnConfirmOtherType_clicked()
{
    flagSetup_rBTypeIgnore = true;
    //判断其他选项是否都没有选中，且其他格式的输入也为空，如果都满足，要将"不限类型"按钮设置为选中
    if (isAllUnchecked())
    {
        ui->tBSelectedType->setText("不限类型");
        ui->rBTypeIgnore->setChecked(true);
    }
    else
    {
        ui->rBTypeIgnore->setChecked(false);
    }
    flagSetup_rBTypeIgnore = false; //将"不限类型"设定成非选中后，要将标志重置为false

    QString otherTypeStr = ui->leOtherType->text();
    m_eBookOtherType.clear();

    //每次都清空m_eBookType里不在限定类型选项中的文件类型
    QStringList type;
    type <<"pdf"<<"epub"<<"azw3"<<"mobi"<<"caj"<<"doc"<<"docx"<<"txt";
    QStringList temp;
    for (QString strType : m_eBookType)
    {
        if (type.contains(strType))
        {
            temp.append(strType);
        }
    }
    m_eBookType = temp;

    //对输入进行分割
    QStringList list = otherTypeStr.split(";");
    for (QString s : list)
    {
        if (s.length() > 0)
        {
            s = s.trimmed().toLower();
            m_eBookOtherType.append(s);
        }
    }

    //m_eBookOtherType去重
    QStringList temp_eBookOtherType;
    QString strOtherType = "";
    for(QString s : m_eBookOtherType)
    {
        if (!temp_eBookOtherType.contains(s))
        {
            temp_eBookOtherType.append(s);
        }
    }
    m_eBookOtherType = temp_eBookOtherType;

    //手动添加的文件类型保存到m_eBookType变量
    if (m_eBookOtherType.size() > 0)
    {
        for (QString str : m_eBookOtherType)
        {
            if (!m_eBookType.contains(str))
            {
                m_eBookType.append(str);
            }
        }
    }

    //在界面已选的文件类型
    if (!isAllUnchecked())
    {
        displaySelectType();
    }
}

void EbookPath::on_cB_pdf_stateChanged(int arg1)
{
    subTypeSelect(arg1,"pdf");
}

void EbookPath::on_cB_epub_stateChanged(int arg1)
{
    subTypeSelect(arg1,"epub");
}

void EbookPath::on_cB_azw3_stateChanged(int arg1)
{
    subTypeSelect(arg1,"azw3");
}

void EbookPath::on_cB_mobi_stateChanged(int arg1)
{
    subTypeSelect(arg1,"mobi");
}

void EbookPath::on_cB_caj_stateChanged(int arg1)
{
    subTypeSelect(arg1,"caj");
}

void EbookPath::on_cB_docOrdocx_stateChanged(int arg1)
{
    subTypeSelect(arg1,"doc");
    subTypeSelect(arg1,"docx");
}

void EbookPath::on_cB_txt_stateChanged(int arg1)
{
    subTypeSelect(arg1,"txt");
}

//选择本地电子书所在路径
void EbookPath::on_ptnAddDir_clicked()
{
    //文件夹可多选，查阅资料说这段可能会出现弹窗卡死，测试没出现过，具体未知。
    QFileDialog fileDlg(nullptr,QObject::tr("请选择电子书所在路径"),QDir::currentPath());
    fileDlg.setWindowFlags(Qt::WindowStaysOnTopHint);
    fileDlg.setOption(QFileDialog::DontUseNativeDialog, true);
    fileDlg.setFileMode(QFileDialog::DirectoryOnly);
    QListView *pListView = fileDlg.findChild<QListView*>();
    QTreeView *pTreeView = fileDlg.findChild<QTreeView*>();
    if (pListView)
    {
        pListView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    }
    if (pTreeView)
    {
        pTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    }

    QStringList dirList;
    if (fileDlg.exec())
    {
        dirList = fileDlg.selectedFiles();
    }
    else
    {
        return;  //没有选择路径，直接返回
    }

    //可能会添加重复的目录，去重
    for (QString s : dirList)
    {
        if (!m_dirVec.contains(s))
        {
            m_dirVec.push_back(s);
        }
    }

    //显示到listWidget
    qDebug() << "-->m_dirVec.size=" << m_dirVec.size();
    ui->listWidgetDir->clear();
    for (QString dir : m_dirVec)
    {
        QListWidgetItem *item = new QListWidgetItem;
        item->setText(dir);
        ui->listWidgetDir->addItem(item);
        ui->listWidgetDir->setCurrentItem(item); //默认选中刚添加的行
    }

    //将路径加入数据库
    Sql::getInstance()->addBookDir2db(m_dirVec);

    //将删除按钮可清空按钮设置为可用
    ui->ptnDeleteDir->setEnabled(true);
    ui->ptnClearDir->setEnabled(true);
}

//移除对应的路径
void EbookPath::on_ptnDeleteDir_clicked()
{
    QMessageBox msgBox(QMessageBox::Warning, tr("警告"),tr("移除路径将清除该目录下的文件记录，确定要执行该操作吗？")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if (msgBox.exec() == QMessageBox::Yes)
    {
        QListWidgetItem *item = ui->listWidgetDir->currentItem();
        //从m_dirVec变量中删除选中的项
        QString delDir = item->text();
        m_dirVec.remove(m_dirVec.indexOf(delDir));

        //删除bookdir数据表中对应的项
        Sql::getInstance()->delBookDir(delDir);

        //删除数据表ebook中对应该路径的记录
        Sql::getInstance()->clearBookInfoBasisToBookdir(delDir);

        //删除listWidget中对应的项
        delete item;

        //设置删除按钮和清空按钮为不可用
        if (ui->listWidgetDir->count() == 0)
        {
            ui->ptnDeleteDir->setEnabled(false);
            ui->ptnClearDir->setEnabled(false);
            ui->ptnAddDir->setFocus();
        }
        emit loadFileSuccess();
    }
}

//清空所选路径
void EbookPath::on_ptnClearDir_clicked()
{
    QMessageBox msgBox(QMessageBox::Warning, tr("警告"),tr("清空路径将清空所有数据，确定要执行该操作吗？")
                       ,QMessageBox::Yes|QMessageBox::No,this);
    if (msgBox.exec() == QMessageBox::Yes)
    {
        clearAll();
        emit loadFileSuccess();
    }
}

//根据选定的文件类型，从路径中把文件信息载入到数据库
void EbookPath::on_ptnAddFileFromDir2db_clicked()
{ 
    auto sql = Sql::getInstance();
    EbookInfo ebook;
    QList<EbookInfo> ebookList;

    if (m_dirVec.size() == 0)
    {
        QMessageBox::warning(this,"警告","路径为空，请先添加电子书所在路径");
        return;
    }

    for(QString dirStr : m_dirVec)
    {
        QDir dir(dirStr);
        for(QFileInfo info : dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
        {
            QString fileName = info.fileName();
            QString filePath = info.filePath();
            QString suffix = info.suffix().toLower();
            if (!m_eBookType.isEmpty())
            {
                //如果选择特定类型，就按选定的文件类型添加
                if (m_eBookType.contains(suffix))
                {
                    ebook.bookname = fileName;
                    ebook.booktype = suffix;
                    ebook.bookpath = filePath;
                    ebook.bookdir = dirStr;
                    ebookList.push_back(ebook);
                }
            }
            else
            {
                //如果不限定文件类型，全部添加，只要是文件即添加
                ebook.bookname = fileName;
                ebook.booktype = suffix;
                ebook.bookpath = filePath;
                ebook.bookdir = dirStr;
                ebookList.push_back(ebook);
            }
        }
    }

    if (ebookList.size() > 0)
    {
        if (!m_eBookType.isEmpty())
        {
            QString selectBooktypeStr;
            for (int i = 0; i < m_eBookType.size(); ++i)
            {
                selectBooktypeStr.append(m_eBookType[i]);
                if (i != m_eBookType.size()-1)
                {
                    selectBooktypeStr.append(",");
                }
            }

            //每次更新会把书籍类型更新到ebooktype数据表中，如果下一次更改要载入的书籍类型，会将原来保存在数据表中的信息清除掉
            QStringList willRemoveBooktypeList;
            QStringList existBooktypeList = sql->getBookTypeList();
            for (QString existBooktype : existBooktypeList)
            {
                if (!m_eBookType.contains(existBooktype))
                {
                    qDebug() << "existBooktype" << existBooktype;
                    willRemoveBooktypeList.append(existBooktype);
                }
            }

            if (willRemoveBooktypeList.size()>0)
            {
                QString removeBooktypeStr;
                for (int i = 0; i < willRemoveBooktypeList.size(); ++i)
                {
                    removeBooktypeStr.append(willRemoveBooktypeList[i]);
                    if (i != willRemoveBooktypeList.size()-1)
                    {
                        removeBooktypeStr.append(",");
                    }
                }

                QMessageBox msgBox(QMessageBox::Warning, tr("警告"),
                                   QString("选定的文件类型有更改，您选中了这些文件类型：%1，取消了这些文件类型：%2，"
                                           "将会删除这些取消了的文件类型的文件数据，确定要执行该操作吗？").
                                   arg(selectBooktypeStr).arg(removeBooktypeStr),
                                   QMessageBox::Yes|QMessageBox::No,this);
                if (msgBox.exec() == QMessageBox::No)
                {
                    return;
                }
                for (QString existBooktype : willRemoveBooktypeList)
                {
                     sql->clearBookInfoBasisToBooktype(existBooktype);
                }
            }
        }

        //根据选定文件类型从所添加的路径中载入文件到数据表，同时也载入文件类型到数据表，两张表
        if (sql->addBookinfo(ebookList) && sql->addBooktype2db(m_eBookType))
        {
            emit loadFileSuccess();
            QMessageBox::information(this,"信息",QString("载入数据库成功，共%1个文件").arg(ebookList.size()));
        }
        else
        {
            QMessageBox::critical(this,"错误","载入数据库失败");
        }
    }
    else
    {
        QMessageBox::information(this,"信息",QString("所添加路径下没有所选定文件类型的文件"));
    }
}
